/*
 * oh323.h
 *
 * Header file for OpenH323 Channel Driver for ASTERISK PBX.
 *  
 * Copyright (C) 2002-2005 Inaccess Networks.
 * Michael Manousos <manousos@inaccessnetworks.com>
 *
 * This file is part of "H.323 support for ASTERISK"
 *
 * "H.323 support for ASTERISK" is free software;
 * you can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation;
 * either version 2 of the License, or (at your option) any later version. 
 *
 * "H.323 support for ASTERISK" is distributed in the hope that it will be 
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details. 
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 *
 * $Id: oh323.h,v 1.2 2010/05/04 09:02:57 mmanousos Exp $
 *
 */

#ifndef _ASTERISK_OH323_H
#define _ASTERISK_OH323_H

#define AST_OH323_MAX_CALLS			200
#define	AST_OH323_FIFO_PREFIX		"audiosocket:"
#define	AST_OH323_MAX_CALLED_ADDR	256
#define	AST_OH323_MAX_CALL_TOK		128
#define	AST_OH323_MAX_CALL_ADDR		128

#define	MAX_FIFO_NAME		30
#define	MAX_EXCEPTION_DATA	256
#define	OH323_CAPABILITY_FULLBANDWIDTH	0x7fffffff
#define	RTPSTATS_MAX_NUM	5
#define	OH323_MAX_BUF		2048
#define	OH323_MAX_QBUF		2048
#define	OH323_MAX_EXTNAME	64

/* OpenH323 channel clearing conditions (internal) */
#define	OH323_CLEAR_NULL	0
#define	OH323_CLEAR_LOC		1
#define	OH323_CLEAR_REM		2

/* OpenH323 channel events (internal usage) */
#define	OH323_EVENT_NULL		0
#define	OH323_EVENT_TERM		1
#define	OH323_EVENT_EXCE		2	
#define	OH323_EVENT_NTFY		3
#define	OH323_EVENT_FDUPDATE	4

/* Version stuff */
#define	OH323_VERSION_MAJOR		0
#define	OH323_VERSION_MINOR		8
#define	OH323_VERSION_BUILD		0

/* OpenH323 channel signaling states (internal usage) */
#define	OH323_STATE_NULL		1
#define	OH323_STATE_INIT		2
#define	OH323_STATE_RING		3
#define	OH323_STATE_RINGING		4	
#define	OH323_STATE_ESTABLISHED	5
#define	OH323_STATE_CLEARED		6

/* Request types */
#define	REQ_CALL		1
#define	REQ_ANSWER		2
#define	REQ_DIGIT		3
#define	REQ_TEXT		4
#define	REQ_INDICATE	5
#define	REQ_HANGUP		6

#ifdef DO_CRASH
#define CRASH do { fprintf(stderr, "!! Forcing immediate crash a-la abort !!\n"); *((int *)0) = 0; } while(0)
#else
#define CRASH do { } while(0)
#endif

typedef struct {
	int   num;
	char *str;
} num_str_t;

/* Debug stuff */
#define	MARKER_INIT	static int oh323_marker = 0
#define MARKER(str) \
	do { \
		if (oh323_marker) { \
			struct timeval tv; \
			if (gettimeofday(&tv, NULL) < 0) \
				break; \
			printf("MARK [%ld.%06ld] [0x%08x] %s %s.\n", (long)tv.tv_sec, (long)tv.tv_usec, \
						(int)pthread_self(), __FUNCTION__, str); \
		} \
	} while (0)

#define	MARK_IN() 		MARKER("IN")
#define	MARK_OUT()		MARKER("OUT")
#define	MYMARK(msg)		MARKER(msg)

#define	ISTATE_LOG(olds, news)	if (option_debug) \
									ast_log(LOG_DEBUG, "NEW STATE: %s --> %s\n",\
											get_str(state_str, olds), \
											get_str(state_str, news))

/***************************************************************************************/
/* Macros defined here for object and object list manipulation:
 *
 *  OBJLIST_DATA
 *  OBJLIST_DEFINE
 *  OBJLIST_DEFINE_STATIC
 *  OBJLIST_INIT
 *  OBJLIST_INSERT
 *  OBJLIST_EXTRACT
 *  OBJ_ALLOC
 *  OBJ_FREE
 *
 */
#define	OBJLIST_DATA(type) \
	type *next, *prev

#define	OBJLIST_DEFINE(type, list) \
	struct { \
		type *head; \
		type *tail; \
		long int inserts, extracts; \
		ast_mutex_t lock; \
	} list

#define	OBJLIST_DEFINE_STATIC(type, list) \
	static struct { \
		type *head; \
		type *tail; \
		long int inserts, extracts; \
		ast_mutex_t lock; \
	} list

#define	OBJLIST_INIT(list) \
	do { \
		(list)->head = NULL; \
		(list)->tail = NULL; \
		(list)->inserts = 0; \
		(list)->extracts = 0; \
		ast_mutex_init(&((list)->lock)); \
	} while(0)

#define OBJLIST_INSERT(list, element) \
	do { \
		ast_mutex_lock(&((list)->lock)); \
		++((list)->inserts); \
		if ((list)->head == NULL) { \
			/* Empty list */ \
			(list)->head = (element); \
			(list)->tail = (element); \
			(element)->next = NULL; \
			(element)->prev = NULL; \
		} else { \
			((list)->head)->prev = (element); \
			(element)->next = (list)->head; \
			(element)->prev = NULL; \
			(list)->head = (element); \
		} \
		ast_mutex_unlock(&((list)->lock)); \
	} while(0)

#define	OBJLIST_EXTRACT(list, element) \
	do { \
		ast_mutex_lock(&((list)->lock)); \
		(element) = NULL; \
		if ((list)->tail != NULL) { \
			++((list)->extracts); \
			(element) = (list)->tail; \
			if ((list)->tail == (list)->head) { \
				/* List is now empty */ \
				(list)->tail = NULL; \
				(list)->head = NULL; \
			} else { \
				/* Unlink the last one */ \
				(list)->tail = (element)->prev; \
				((list)->tail)->next = NULL; \
			} \
			(element)->prev = NULL; \
			(element)->next = NULL; \
		} \
		ast_mutex_unlock(&((list)->lock)); \
	} while(0)

#define	OBJ_ALLOC(type, element) \
	do { \
		(element) = (type*)malloc(sizeof(type)); \
		if (!(element)) { \
			ast_log(LOG_ERROR, "Malloc failed.\n"); \
			CRASH; \
		} else { \
			memset((char *)(element), 0, sizeof(type)); \
		} \
	} while(0)

#define	OBJ_FREE(element) \
	do { \
		free(element); \
	} while(0)

#endif
